#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "debug.h"
#include "os_api.h"
#include "ps_api.h"
#include "dev_api.h"
#include "mqttclient.h"
#include "os_api.h"
#include "debug.h"
#include "hal/gpio.h"
#include "lpconfig.h"


static OS_HISR 	gpio_detect_hisr_ref = NULL;
static OSATimerRef gpio_detect_timer_ref = NULL;
static OSFlagRef  gpio_detect_flag_ref = NULL;
static OSATaskRef gpio_detect_task_ref = NULL;

static void* gpio_detect_task_stack = NULL;

UINT32 gpio_detect_gpio = 06;
UINT32 gpio_debounce_time = 100;    //ms

#define GPIO_DET_BIT		0x100



void gpio_wakeup(void)
{
    lp_wakeup();
}

void gpio_sleep(void)
{
    lp_sleep();
}


UINT32 get_gpio_status(void)
{
    UINT32 value;

	value=hal_GpioIn(gpio_detect_gpio);

	return value;
}

void gpio_det_lisr(void)
{
	int ret;

	hal_GpioDisableEdgeDet(gpio_detect_gpio, GPIO_TWO_EDGE);
	
	ret = OS_Activate_HISR(&gpio_detect_hisr_ref);
	ASSERT(ret == OS_SUCCESS);
}


void gpio_det_trigger(void)
{
    if (gpio_detect_flag_ref)
        OSAFlagSet(gpio_detect_flag_ref, GPIO_DET_BIT, OSA_FLAG_OR);
}

void gpio_det_task_entry(void *ptr)
{
	UINT32 value;
    GPIOReturnCode ret;
	UINT32 flag_value = 0;
	UINT32 flag_mask = GPIO_DET_BIT;
	UINT32 gpio_status;

	LOG_PRINTF("gpio_det_task_entry");

	while(1)
	{
		OSAFlagWait( gpio_detect_flag_ref, flag_mask, OSA_FLAG_OR_CLEAR, &flag_value, OSA_SUSPEND);
		
		if(flag_value & GPIO_DET_BIT)
		{
			gpio_status = get_gpio_status();

			LOG_PRINTF("gpio_det_task_entry gpio_status = %u", gpio_status);

			if (gpio_status == 0){
				gpio_wakeup();		
			}else{
				gpio_sleep();						
			}
		}
	}
}

void gpio_det_timer_handler(UINT32 arg)
{
	OS_STATUS os_status;
	UINT32 gpio_status;

	gpio_status = get_gpio_status();

	LOG_PRINTF("gpio_status = %u", gpio_status);
	gpio_det_trigger();
    
	hal_GpioEnableEdgeDet(gpio_detect_gpio, GPIO_TWO_EDGE);
}

static void gpio_det_hisr(void)
{
	UINT32 timeout;

	OSATimerStop(gpio_detect_timer_ref);

	timeout=gpio_debounce_time/5;

	if(timeout==0)
		timeout=1;

	LOG_PRINTF("gpio_det_hisr %lu, gpio_status=%u", timeout, get_gpio_status());

	OSATimerStart(gpio_detect_timer_ref,
                             timeout,
                             0,
                             gpio_det_timer_handler,
                             0);
}

void lqgpio_main(void)
{
    int ret;
	GPIOConfiguration config;

    OSATimerCreate(&gpio_detect_timer_ref);
    OSAFlagCreate( &gpio_detect_flag_ref);  
    Os_Create_HISR(&gpio_detect_hisr_ref, "gpio_det_hisr", gpio_det_hisr, 2);

	gpio_detect_task_ref = malloc(1024*2);
	ASSERT(gpio_detect_task_ref != NULL);	
    ret = OSATaskCreate(&gpio_detect_task_ref, gpio_detect_task_ref, (1024*2), 100, "gpio_det_task_entry", gpio_det_task_entry, NULL);
    ASSERT(ret == OS_SUCCESS);

	config.pinDir = GPIO_IN_PIN;
	config.pinEd = GPIO_TWO_EDGE;
	config.pinPull = GPIO_PULLUP_ENABLE;
	config.isr = gpio_det_lisr;

    hal_ConfigGpio(gpio_detect_gpio,config);
}